package com.jymj.common.filter;

import com.alibaba.fastjson.JSON;
import com.jymj.common.shiro.JwtTokenUtil;
import com.jymj.entity.SysUserEntity;
import com.jymj.utils.R;
import com.jymj.utils.ShiroUtils;
import io.jsonwebtoken.ExpiredJwtException;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class AuthenticationValidateFilter extends AccessControlFilter {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    //@Value("${jwt.header}")
    private final String auth = "Authorization";

    //@Value("${jwt.refreshinterval}")
    private final int refreshInterval = 30;

    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {

        System.out.print(servletRequest.getLocale());
        return false;
    }

    public static List noAfc() {
        List list = new ArrayList();
        list.add("/applyFile/");
        list.add("/applyChildFile/");
        return list;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        //是否验证通过
        boolean bool = false;
        HttpServletRequest req = WebUtils.toHttp(servletRequest);
        //请求路径
        StringBuffer path = req.getRequestURL();
        List list = noAfc();
        for (Object pa : list) {
            boolean bb = path.indexOf(pa.toString()) != -1;
            if (bb) {
                return true;
            }
        }
        SysUserEntity user = ShiroUtils.getUserEntity();
        if (user == null || user.getUserId() == null) {
            R r = new R();
            r.put("code", 401);
            r.put("msg", "用户未登陆");
            String json = JSON.toJSONString(r);
            servletResponse.getWriter().print(json);
            return false;
        }
        try {
            String requestHeader = req.getHeader(auth);
            logger.info(requestHeader);
            String username;
            if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
                String authToken = requestHeader.substring(7);
                try {
                    username = JwtTokenUtil.getUsernameFromToken(authToken);
                    if (null != username) {
                         /*String redisVal = RedisUtil.getString(username);
                        if (redisVal == null) {*/
                            Date d = JwtTokenUtil.getIssuedAtDateFromToken(authToken);
                            if (!isBefore(AddDay(d))) {
                                String newAuth = JwtTokenUtil.refreshToken(authToken);
                                ((HttpServletResponse) servletResponse).setHeader(auth, newAuth);
                            }
                            bool = true;
                       /* } else {
                            bool = false;
                        }*/
                    }
                } catch (IllegalArgumentException e) {
                    logger.error("an error occured during getting username from token", e);
                } catch (ExpiredJwtException e) {
                    logger.warn("the token is expired and not valid anymore", e);
                }
            } else {
                logger.warn("couldn't find bearer string, will ignore the header");
            }
        } catch (Exception e) {
            logger.warn("onAccessDenied:", e);
            bool = false;
        } finally {
            if (!bool) {
                R r = new R();
                r.put("code", 401);
                r.put("msg", "Unauthorized");
                String json = JSON.toJSONString(r);
                servletResponse.getWriter().print(json);
            }
            return bool;
        }
    }

    private boolean isBefore(Date date) {
        Date now = new Date();
        return now.before(date);
    }

    private Date AddDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        //cal.add(Calendar.HOUR, refreshInterval);
        cal.add(Calendar.MINUTE, refreshInterval);
        return cal.getTime();
    }
}
